using System;
using System.Collections;
using System.Xml;

using LocalBoard.Domain;

using NUnit.Framework;

namespace LocalBoard.Persistence
{
	[TestFixture]
	public class TestAccessor
	{
		protected IAttachmentAccessor _attachmentAccessor;
		protected IBoardAccessor _boardAccessor;
		protected IClubAccessor _clubAccessor;
		protected ICommentAccessor _commentAccessor;
		protected IMessageAccessor _messageAccessor;
		protected IPollItemAccessor _pollItemAccessor;
		protected IProfileAccessor _profileAccessor;
		protected IUserRoleAccessor _userRoleAccessor;
		protected IClubProfileAccessor _clubProfileAccessor;

		protected Club _club;

		[SetUp]
		public void setUp()
		{
			IAccessorFactory accessorFactory = new MockAccessorFactory();
			_attachmentAccessor = accessorFactory.GetAttachmentAccessor();
			_boardAccessor = accessorFactory.GetBoardAccessor();
			_clubAccessor = accessorFactory.GetClubAccessor();
			_commentAccessor = accessorFactory.GetCommentAccessor();
			_messageAccessor = accessorFactory.GetMessageAccessor();
			_pollItemAccessor = accessorFactory.GetPollItemAccessor();
			_profileAccessor = accessorFactory.GetProfileAccessor();
			_userRoleAccessor = accessorFactory.GetUserRoleAccessor();
			_clubProfileAccessor = accessorFactory.GetClubProfileAccessor();

			_club = _clubAccessor.Get(1);
		}

		[TearDown]
		public void tearDown()
		{
			MockAccessorFactory.ResetDataTable();

			_attachmentAccessor = null;
			_boardAccessor = null;
			_clubAccessor = null;
			_commentAccessor = null;
			_messageAccessor = null;
			_pollItemAccessor = null;
			_profileAccessor = null;
			_userRoleAccessor = null;
			_clubProfileAccessor = null;

			_club = null;
		}

		[Test]
		public void testClubAccessor()
		{
			string club3Info = "<info>test info</info>";
			XmlDocument doc = new XmlDocument();
			doc.LoadXml(club3Info);
			Club testClub1 = new Club("Club1", "Club 1", 1, "", "", null);
			Club testClub2 = new Club("Club2", "Club 2", 1, "", "", null);
			Club testClub3 = new Club("Club3", "Club 3", 1, "", "", doc);

			Club newClub = _clubAccessor.Get(_clubAccessor.Insert(testClub1));
			Assert.IsTrue(newClub.Name == "Club 1");

			newClub = _clubAccessor.Get(_clubAccessor.Insert(testClub2));
			Assert.IsTrue(newClub.Name == "Club 2");

			newClub = _clubAccessor.Get(_clubAccessor.Insert(testClub3));
			Assert.IsTrue(newClub.Name == "Club 3");
			Assert.AreEqual(club3Info, newClub.Information.OuterXml);

			ArrayList clubList = _clubAccessor.GetClubList();
			Assert.IsTrue(clubList.Count == 5); //including 2 default clubs

			newClub.Name = "Club 3 name changed";
			_clubAccessor.Update(newClub);
			Club changedClub = _clubAccessor.Get(newClub.Id);
			Assert.IsTrue(changedClub.Name != "Club 3");

			_clubAccessor.Delete(changedClub.Id);
			clubList = _clubAccessor.GetClubList();
			Assert.IsTrue(clubList.Count == 4); //including 2 default clubs
		}

		[Test]
		public void testBoardAccessor()
		{
			Board testBoard1 = new Board("Board 1", null, 0, 0, _club.Id, BoardViewType.List);
			Board testBoard2 = new Board("Board 2", null, 0, 0, _club.Id, BoardViewType.List);
			Board testBoard3 = new Board("Board 3", null, 0, 0, _club.Id, BoardViewType.List);

			Board newBoard = _boardAccessor.Get(_boardAccessor.Insert(testBoard1));
			Assert.IsTrue(newBoard.Name == "Board 1");

			newBoard = _boardAccessor.Get(_boardAccessor.Insert(testBoard2));
			Assert.IsTrue(newBoard.Name == "Board 2");

			newBoard = _boardAccessor.Get(_boardAccessor.Insert(testBoard3));
			Assert.IsTrue(newBoard.Name == "Board 3");

			ArrayList boardList = _boardAccessor.GetBoardListByClubId(_club.Id);
			Assert.IsTrue(boardList.Count == 3);

			newBoard.Name = "Board 3 name changed";
			_boardAccessor.Update(newBoard);
			Board changedBoard = _boardAccessor.Get(newBoard.Id);
			Assert.IsTrue(changedBoard.Name != "Board 3");

			int profileId = _profileAccessor.Insert(new Profile("testuser", "username", "testpwd", "test@test.com"));
			XmlDocument doc = new XmlDocument();
			doc.LoadXml("<profile>test</profile>");
			_clubProfileAccessor.Insert(profileId, doc, changedBoard.ClubId);
			_boardAccessor.AssignManagerToBoard(profileId, changedBoard.Id);
			changedBoard = _boardAccessor.Get(changedBoard.Id);
			Assert.IsTrue(changedBoard.Manager.Id == profileId);

			_boardAccessor.Delete(changedBoard.Id);
			boardList = _boardAccessor.GetBoardListByClubId(_club.Id);
			Assert.IsTrue(boardList.Count == 2);

			_profileAccessor.Delete(profileId);
		}

		[Test]
		public void testProfileAccessor()
		{
			Profile testProfile1 = Profile.CreateProfile("userId1", "userName 1", "password1", "email1@mail.com", "c:\\temp\\photo1.gif", "testBio");
			Profile testProfile2 = new Profile("userId2", "userName 2", "password2", "email2@mail.com");
			Profile testProfile3 = new Profile("userId3", "userName 3", "password3", "email3@mail.com");
			Profile testProfile4 = new Profile("userId4", "userName 4", "password4", "email4@mail.com");

			Profile newProfile = _profileAccessor.Get(_profileAccessor.Insert(testProfile1));
			Assert.AreEqual("userId1", newProfile.UserId);
			Assert.AreEqual("c:\\temp\\photo1.gif", newProfile.PhotoPath);
			Assert.AreEqual("testBio", newProfile.CustomInfo);

			newProfile = _profileAccessor.Get(_profileAccessor.Insert(testProfile2));
			Assert.AreEqual("userId2", newProfile.UserId);

			newProfile = _profileAccessor.Get(_profileAccessor.Insert(testProfile3));
			Assert.AreEqual("userId3", newProfile.UserId);

			newProfile = _profileAccessor.Get(_profileAccessor.Insert(testProfile4));
			Assert.AreEqual("userId4", newProfile.UserId);

			ArrayList profileList = _profileAccessor.GetAllUserProfiles();
			Assert.AreEqual(5, profileList.Count); //including anonymous user

			newProfile.UserName = "userName 4 changed";
			_profileAccessor.Update(newProfile);
			Profile changedProfile = _profileAccessor.GetProfileByUserId(newProfile.UserId);
			Assert.IsTrue(changedProfile.UserName != "userName 4");

			newProfile.UserName = "userName 4 changed again";
			_profileAccessor.Update(newProfile);
			changedProfile = _profileAccessor.GetProfileByUserIdAndPassword(newProfile.UserId, newProfile.Password);
			Assert.IsTrue(changedProfile.UserName != "userName 4 changed");

			_profileAccessor.Delete(newProfile.Id);
			profileList = _profileAccessor.GetAllUserProfiles();
			Assert.AreEqual(4, profileList.Count); //including anonymous user
		}

		[Test]
		public void testUserRoleAccessor()
		{
			int role1Id = _userRoleAccessor.Insert("role1");
			int role2Id = _userRoleAccessor.Insert("role2");
			int role3Id = _userRoleAccessor.Insert("role3");

			Hashtable allRoles = _userRoleAccessor.GetAllUserRoles();
			Assert.IsNotNull(allRoles);
			Assert.AreEqual(4, allRoles.Count); //Including admin role

			UserRole role1 = allRoles[role1Id] as UserRole;
			role1.Name = "role1 name changed";
			_userRoleAccessor.Update(role1);
			allRoles = _userRoleAccessor.GetAllUserRoles();
			role1 = allRoles[role1Id] as UserRole;
			Assert.IsTrue(role1.Name != "role1");

			_userRoleAccessor.Delete(role1.Id);
			allRoles = _userRoleAccessor.GetAllUserRoles();
			Assert.IsNotNull(allRoles);
			Assert.AreEqual(3, allRoles.Count); //Including amdin role

			int profileId = _profileAccessor.Insert(new Profile("userId4", "userName 4", "password4", "email4@mail.com"));
			_userRoleAccessor.AddRoleToProfile(role2Id, profileId);
			_userRoleAccessor.AddRoleToProfile(role3Id, profileId);
			ArrayList profileRoles = _userRoleAccessor.GetRolesByProfileId(profileId);
			Assert.IsTrue(profileRoles != null && profileRoles.Count == 2);

			_userRoleAccessor.DeleteRoleFromProfile(role2Id, profileId);
			profileRoles = _userRoleAccessor.GetRolesByProfileId(profileId);
			Assert.IsTrue(profileRoles != null && profileRoles.Count == 1);

			UserRole role3 = profileRoles[0] as UserRole;
			Assert.IsTrue(role3.Name == "role3");
		}

		[Test]
		public void testMessageAccessor()
		{
			int board1Id = _boardAccessor.Insert(new Board("Board 1", null, 0, 0, _club.Id, BoardViewType.List));

			Profile testProfile1 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId1", "userName 1", "password1", "email1@mail.com")));
			Profile testProfile2 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId2", "userName 2", "password2", "email2@mail.com")));
			Profile testProfile3 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId3", "userName 3", "password3", "email3@mail.com")));

			int msg1Id = _messageAccessor.Insert(new Message("subject1", "body1", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg2Id = _messageAccessor.Insert(new Message("subject2", "body2", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg3Id = _messageAccessor.Insert(new Message("subject3", "body3", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg4Id = _messageAccessor.Insert(new Message("subject4", "body4", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg5Id = _messageAccessor.Insert(new Message("subject5", "body5", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg6Id = _messageAccessor.Insert(new Message("subject6", "body6", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg7Id = _messageAccessor.Insert(new Message("subject7", "body7", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));

			ArrayList messageList = _messageAccessor.GetMessageListByBoardId(board1Id, 10, 1);
			Assert.IsTrue(messageList.Count == 7 && _messageAccessor.GetTotalRootMessageCountByBoardId(board1Id) == 7);

			messageList = _messageAccessor.GetMessageListByBoardId(board1Id, 5, 2);
			Assert.IsTrue(messageList.Count == 2 && _messageAccessor.GetTotalRootMessageCountByBoardId(board1Id) == 7);

			//Author check
			Message newMessage2 = _messageAccessor.Get(msg2Id);
			Assert.IsNotNull(newMessage2.Author);
			Assert.AreEqual(testProfile1.UserId, newMessage2.Author.UserId);

			Message newMessage = _messageAccessor.Get(msg1Id);
			newMessage.Subject = "subject1 changed";
			newMessage.Body = "body1 changed";
			_messageAccessor.Update(newMessage);
			Assert.IsTrue(newMessage.Subject != "subject1" && newMessage.Body != "body1");

			int reply1_1Id = _messageAccessor.Insert(new Message("Re:subject1", "Re:body1", testProfile2.UserName, testProfile2.UserId, testProfile2, board1Id, _club.Id, msg1Id));
			int reply2_1Id = _messageAccessor.Insert(new Message("Re:subject1", "Re:body1", testProfile2.UserName, testProfile2.UserId, testProfile2, board1Id, _club.Id, msg1Id));
			int reply1_1_1Id = _messageAccessor.Insert(new Message("Rd:Re:subject1", "Rd:Re:body1", testProfile3.UserName, testProfile3.UserId, testProfile3, board1Id, _club.Id, reply1_1Id));
			Message rootMessage = _messageAccessor.Get(msg1Id);
			Assert.IsTrue(rootMessage.Replies.Count == 2);
			Assert.IsTrue(((Message)rootMessage.Replies[0]).Replies.Count == 1);

			_messageAccessor.Delete(msg1Id);
			messageList = _messageAccessor.GetMessageListByBoardId(board1Id, 10, 1);
			Assert.IsTrue(messageList.Count == 6 && _messageAccessor.GetTotalRootMessageCountByBoardId(board1Id) == 6);

			Assert.IsTrue(_messageAccessor.Get(reply1_1Id) == null);
			Assert.IsTrue(_messageAccessor.Get(reply2_1Id) == null);
			Assert.IsTrue(_messageAccessor.Get(reply1_1_1Id) == null);

			_messageAccessor.InsertVote(msg5Id, testProfile1.Id, 4);
			_messageAccessor.InsertVote(msg5Id, testProfile2.Id, 6);
			Assert.AreEqual(2, _messageAccessor.GetVoteList(msg5Id).Count);
			foreach(Vote vote in _messageAccessor.GetVoteList(msg5Id))
			{
				if(vote.ProfileId == testProfile1.Id)
					Assert.AreEqual(4, vote.Point);
				else if(vote.ProfileId == testProfile2.Id)
					Assert.AreEqual(6, vote.Point);
			}
			_messageAccessor.InsertVote(msg4Id, testProfile2.Id, 7);
			Assert.AreEqual(1, _messageAccessor.GetVoteList(msg4Id).Count);
			foreach(Vote vote in _messageAccessor.GetVoteList(msg4Id))
			{
				Assert.AreEqual(7, vote.Point);
			}
		}

		[Test]
		public void testAttachmentAccessor()
		{
			int board1Id = _boardAccessor.Insert(new Board("Board 1", null, 0, 0, _club.Id, BoardViewType.List));
			Profile testProfile1 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId1", "userName 1", "password1", "email1@mail.com")));
			int msg1Id = _messageAccessor.Insert(new Message("subject1", "body1", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg2Id = _messageAccessor.Insert(new Message("subject2", "body2", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));

			int attachment1Id = _attachmentAccessor.Insert(new Attachment("attachment1", 100, "testPath/test"), msg1Id);
			_attachmentAccessor.Insert(new Attachment("attachment1-2", 50, "testPath/test"), msg1Id);
			int attachment2Id = _attachmentAccessor.Insert(new Attachment("attachment2", 100, "testPath/test"), msg2Id);
			Message message1 = _messageAccessor.Get(msg1Id);
			Message message2 = _messageAccessor.Get(msg2Id);
			Assert.IsTrue(message1.Attachments.Count == 2 && message2.Attachments.Count == 1);

			_attachmentAccessor.Delete(attachment1Id);
			message1 = _messageAccessor.Get(msg1Id);
			_attachmentAccessor.Delete(attachment2Id);
			message2 = _messageAccessor.Get(msg2Id);
			Assert.IsTrue(message1.Attachments.Count == 1 && ((Attachment)message1.Attachments[0]).Name == "attachment1-2" && message2.Attachments.Count == 0);
		}

		[Test]
		public void testCommentAccessor()
		{
			int board1Id = _boardAccessor.Insert(new Board("Board 1", null, 0, 0, _club.Id, BoardViewType.List));
			Profile testProfile1 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId1", "userName 1", "password1", "email1@mail.com")));
			int msg1Id = _messageAccessor.Insert(new Message("subject1", "body1", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg2Id = _messageAccessor.Insert(new Message("subject2", "body2", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));

			int comment1Id = _commentAccessor.Insert(new Comment("comment1", testProfile1.UserName, testProfile1.UserId, testProfile1), msg1Id);
			_commentAccessor.Insert(new Comment("comment1-2", testProfile1.UserName, testProfile1.UserId, testProfile1), msg1Id);
			int comment2Id = _commentAccessor.Insert(new Comment("comment2", testProfile1.UserName, testProfile1.UserId, testProfile1), msg2Id);

			Message message1 = _messageAccessor.Get(msg1Id);
			Message message2 = _messageAccessor.Get(msg2Id);
			Assert.IsTrue(message1.Comments.Count == 2 && message2.Comments.Count == 1);

			_commentAccessor.Delete(comment1Id);
			_commentAccessor.Delete(comment2Id);

			message1 = _messageAccessor.Get(msg1Id);
			message2 = _messageAccessor.Get(msg2Id);

			Assert.IsTrue(message1.Comments.Count == 1 && ((Comment)message1.Comments[0]).Body == "comment1-2" && message2.Comments.Count == 0);

		}

		[Test]
		public void testPollItemAccessor()
		{
			int board1Id = _boardAccessor.Insert(new Board("Board 1", null, 0, 0, _club.Id, BoardViewType.List));
			Profile testProfile1 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId1", "userName 1", "password1", "email1@mail.com")));
			Profile testProfile2 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId2", "userName 2", "password2", "email2@mail.com")));
			Profile testProfile3 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId3", "userName 3", "password3", "email3@mail.com")));
			int msg1Id = _messageAccessor.Insert(new PollMessage("subject1", "body1", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg2Id = _messageAccessor.Insert(new PollMessage("subject2", "body2", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));
			int msg3Id = _messageAccessor.Insert(new PollMessage("subject3", "body3", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));

			int pollItem1_1Id = _pollItemAccessor.Insert(new PollItem("pollItem1-1"), msg1Id);
			int pollItem1_2Id = _pollItemAccessor.Insert(new PollItem("pollItem1-2"), msg1Id);
			int pollItem1_3Id = _pollItemAccessor.Insert(new PollItem("pollItem1-3"), msg1Id);
			int pollItem1_4Id = _pollItemAccessor.Insert(new PollItem("pollItem1-4"), msg1Id);

			int pollItem2_1Id = _pollItemAccessor.Insert(new PollItem("pollItem2-1"), msg2Id);
			int pollItem2_2Id = _pollItemAccessor.Insert(new PollItem("pollItem2-2"), msg2Id);
			int pollItem2_3Id = _pollItemAccessor.Insert(new PollItem("pollItem2-3"), msg2Id);

			int pollItem3_1Id = _pollItemAccessor.Insert(new PollItem("pollItem2-1"), msg3Id);
			int pollItem3_2Id = _pollItemAccessor.Insert(new PollItem("pollItem2-2"), msg3Id);

			PollMessage pollMessage1 = (PollMessage)_messageAccessor.Get(msg1Id);
			PollMessage pollMessage2 = (PollMessage)_messageAccessor.Get(msg2Id);
			PollMessage pollMessage3 = (PollMessage)_messageAccessor.Get(msg3Id);
			Assert.IsTrue(pollMessage1.PollItems.Count == 4 && pollMessage2.PollItems.Count == 3 && pollMessage3.PollItems.Count == 2);

			_pollItemAccessor.PostPoll(pollItem1_1Id, msg1Id, testProfile1.Id);
			_pollItemAccessor.PostPoll(pollItem1_2Id, msg1Id, testProfile2.Id);
			_pollItemAccessor.PostPoll(pollItem2_1Id, msg2Id, testProfile1.Id);
			_pollItemAccessor.PostPoll(pollItem2_2Id, msg2Id, testProfile2.Id);

			pollMessage1 = (PollMessage)_messageAccessor.Get(msg1Id);
			pollMessage2 = (PollMessage)_messageAccessor.Get(msg2Id);
			pollMessage3 = (PollMessage)_messageAccessor.Get(msg3Id);
			Assert.IsTrue(pollMessage1.DidUserVote(testProfile1.Id) && pollMessage1.DidUserVote(testProfile2.Id) && !pollMessage1.DidUserVote(testProfile3.Id) && pollMessage2.DidUserVote(testProfile1.Id) && pollMessage2.DidUserVote(testProfile2.Id) && !pollMessage2.DidUserVote(testProfile3.Id));
			foreach(PollItem item in pollMessage1.PollItems)
			{
				if(item.Id == pollItem1_1Id)
					Assert.IsTrue(item.NumberOfVotes == 1);
				else if(item.Id == pollItem1_2Id)
					Assert.IsTrue(item.NumberOfVotes == 1);
				else
					Assert.IsTrue(item.NumberOfVotes == 0);
			}

			_pollItemAccessor.Delete(pollItem3_1Id, msg3Id);
			pollMessage3 = (PollMessage)_messageAccessor.Get(msg3Id);

			Assert.IsTrue(pollMessage1.PollItems.Count == 4 && pollMessage2.PollItems.Count == 3 && pollMessage3.PollItems.Count == 1);

		}

		[Test]
		[ExpectedException(typeof(Exception))]
		public void testPollItemDelete()
		{
			int board1Id = _boardAccessor.Insert(new Board("Board 1", null, 0, 0, _club.Id, BoardViewType.List));
			Profile testProfile1 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId1", "userName 1", "password1", "email1@mail.com")));
			Profile testProfile2 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId2", "userName 2", "password2", "email2@mail.com")));
			Profile testProfile3 = _profileAccessor.Get(_profileAccessor.Insert(new Profile("userId3", "userName 3", "password3", "email3@mail.com")));
			int msg1Id = _messageAccessor.Insert(new PollMessage("subject1", "body1", testProfile1.UserName, testProfile1.UserId, testProfile1, board1Id, _club.Id, 0));

			int pollItem1_1Id = _pollItemAccessor.Insert(new PollItem("pollItem1-1"), msg1Id);
			int pollItem1_2Id = _pollItemAccessor.Insert(new PollItem("pollItem1-2"), msg1Id);
			int pollItem1_3Id = _pollItemAccessor.Insert(new PollItem("pollItem1-3"), msg1Id);
			int pollItem1_4Id = _pollItemAccessor.Insert(new PollItem("pollItem1-4"), msg1Id);

			PollMessage pollMessage1 = (PollMessage)_messageAccessor.Get(msg1Id);

			_pollItemAccessor.PostPoll(pollItem1_1Id, msg1Id, testProfile1.Id);
			_pollItemAccessor.PostPoll(pollItem1_2Id, msg1Id, testProfile2.Id);

			_pollItemAccessor.Delete(pollItem1_2Id, msg1Id);
		}
	}
}